package com.wejoy.video.middle.station.data.util;

import java.time.*;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * 基于java8 的日期工具类
 * Created by liuyu on 2017/8/18.
 */
public class LocalDateUtils {

    /**
     * 收集起始日期到结束日期之间所有的日期并以集合方式返回
     *
     * @param start LocalDate 开始日期
     * @param end   LocalDate 结束日期
     * @return 返回 String类型 日期 集合
     */
    public static List<String> collectLocalDatesStrByTwoDate(LocalDate start, LocalDate end) {
        // 用起始时间作为流的源头，按照每次加一天的方式创建一个无限流
        return Stream.iterate(start, localDate -> localDate.plusDays(1))
                // 截断无限流，长度为起始时间和结束时间的差+1个
                .limit(ChronoUnit.DAYS.between(start, end) + 1)
                // 由于最后要的是字符串，所以map转换一下
                .map(LocalDate::toString)
                // 把流收集为List
                .collect(Collectors.toList());
    }


    /**
     * 收集起始日期到结束日期之间所有的日期并以集合方式返回
     *
     * @param start String 开始日期
     * @param end   String 结束日期
     * @return 返回 String类型 日期 集合
     */
    public static List<String> collectLocalDatesStrByTwoDateStr(String start, String end) {
        return collectLocalDatesStrByTwoDate(LocalDate.parse(start), LocalDate.parse(end));
    }

    /**
     * 收集起始日期到结束日期之间所有的日期并以集合方式返回
     *
     * @param start LocalDate 开始日期
     * @param end   LocalDate 结束日期
     * @return 返回 LocalDate类型 日期 集合
     */
    public static List<LocalDate> collectLocalDatesByTwoDate(LocalDate start, LocalDate end) {
        return Stream.iterate(start, localDate -> localDate.plusDays(1))
                .limit(ChronoUnit.DAYS.between(start, end) + 1)
                .collect(Collectors.toList());
    }

    /**
     * 收集起始日期到结束日期之间所有的日期并以集合方式返回
     *
     * @param start String 开始日期
     * @param end   String 结束日期
     * @return 返回 LocalDate类型 日期 集合
     */
    public static List<LocalDate> collectLocalDatesByTwoDateStr(String start, String end) {
        return collectLocalDatesByTwoDate(LocalDate.parse(start), LocalDate.parse(end));
    }

    /**
     * 按周收集起始日期到结束日期之间所有的日期并以集合方式返回
     *
     * @param start LocalDate 开始日期
     * @param end   LocalDate 结束日期
     * @return 返回 LocalDate类型 日期 集合
     */
    public static List<LocalDate> collectOfWeekByTwoDate(LocalDate start, LocalDate end) {
        return Stream.iterate(start, localDate -> localDate.plusWeeks(1))
                .limit(ChronoUnit.WEEKS.between(start, end) + 1)
                .collect(Collectors.toList());
    }

    /**
     * 按周收集起始日期到结束日期之间所有的日期并以集合方式返回
     *
     * @param start String 开始日期
     * @param end   String 结束日期
     * @return 返回 LocalDate类型 日期 集合
     */
    public static List<LocalDate> collectOfWeekByTwoDate(String start, String end) {
        return collectOfWeekByTwoDate(LocalDate.parse(start), LocalDate.parse(end));
    }

    /**
     * 按周收集起始日期到结束日期之间所有的日期并以集合方式返回
     *
     * @param start LocalDate 开始日期
     * @param end   LocalDate 结束日期
     * @return 返回 String类型 日期 集合
     */
    public static List<String> collectOfWeekStrByTwoDate(LocalDate start, LocalDate end) {
        return Stream.iterate(start, localDate -> localDate.plusWeeks(1))
                .limit(ChronoUnit.WEEKS.between(start, end) + 1)
                .map(LocalDate::toString)
                .collect(Collectors.toList());
    }

    /**
     * 按周收集起始日期到结束日期之间所有的日期并以集合方式返回
     *
     * @param start String 开始日期
     * @param end   String 结束日期
     * @return 返回 String类型 日期 集合
     */
    public static List<String> collectOfWeekStrByTwoDateStr(String start, String end) {
        return collectOfWeekStrByTwoDate(LocalDate.parse(start), LocalDate.parse(end));
    }

    /**
     * 获取当前时间戳秒数
     */
    public static long getCurrentSecond() {
        return LocalDateTime.now().toEpochSecond(ZoneOffset.of("+8"));
    }

    /**
     * 获取当前时间戳毫秒数
     */
    public static long getCurrentSecondMill() {
        return LocalDateTime.now().toInstant(ZoneOffset.of("+8")).toEpochMilli();
    }

    /**
     * 获取LocaDate得 毫秒数
     */
    public static long getCurrentSecondMillByLocalDate(LocalDate localDate) {
        return localDate.atStartOfDay().toInstant(ZoneOffset.of("+8")).toEpochMilli();
    }

    /**
     * 获取毫秒数
     */
    public static long getCurrentSecondMill(LocalDateTime localDateTime) {
        return localDateTime.toInstant(ZoneOffset.of("+8")).toEpochMilli();
    }

    /**
     * 获取当前时间的小时与分钟
     */
    public static String getNowHourAndMinute() {
        DateTimeFormatter pattern = DateTimeFormatter.ofPattern("HH:mm");
        return pattern.format(LocalDateTime.now());
    }

    /**
     * Date 转 LocalDateTime
     *
     * @param date
     * @return
     */
    public static LocalDateTime dateToLocalDateTime(Date date) {
        Instant instant = date.toInstant();
        ZoneId zoneId = ZoneId.systemDefault();
        return instant.atZone(zoneId).toLocalDateTime();
    }

    /**
     * Date 转 LocalDateTime
     *
     * @param localDateTime
     * @return
     */
    public static Date localDateTimeToDate(LocalDateTime localDateTime) {
        ZoneId zoneId = ZoneId.systemDefault();
        ZonedDateTime zdt = localDateTime.atZone(zoneId);
        return Date.from(zdt.toInstant());
    }

    /**
     * LocalDate转Date
     *
     * @param localDate
     * @return
     */
    public static Date localDateToDate(LocalDate localDate) {
        ZonedDateTime zonedDateTime = localDate.atStartOfDay(ZoneId.systemDefault());
        return Date.from(zonedDateTime.toInstant());
    }

    /**
     * Date转LocalDate
     *
     * @param date
     */
    public static LocalDate dateToLocalDate(Date date) {
        return date.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
    }

    public static void main(String[] args) {
        System.out.println(new Date().toInstant().atZone(ZoneId.systemDefault()).toLocalDate());
    }

    /**
     * 根据年月获取当前月开始时间
     *
     * @param year
     * @param month
     * @return
     */
    public static Date getBeginTimeByYearAndMonth(int year, int month) {
        YearMonth yearMonth = YearMonth.of(year, month);
        LocalDate localDate = yearMonth.atDay(1);
        LocalDateTime startOfDay = localDate.atStartOfDay();
        ZonedDateTime zonedDateTime = startOfDay.atZone(ZoneId.of("Asia/Shanghai"));

        return Date.from(zonedDateTime.toInstant());
    }

    /**
     * 根据年月获取当前月结束时间
     *
     * @param year
     * @param month
     * @return
     */
    public static Date getEndTimeByYearAndMonth(int year, int month) {
        YearMonth yearMonth = YearMonth.of(year, month);
        LocalDate endOfMonth = yearMonth.atEndOfMonth();
        LocalDateTime localDateTime = endOfMonth.atTime(23, 59, 59, 999);
        ZonedDateTime zonedDateTime = localDateTime.atZone(ZoneId.of("Asia/Shanghai"));
        return Date.from(zonedDateTime.toInstant());
    }

    /**
     * 时间戳转localDate
     *
     * @param timestamp
     * @return
     */
    public static LocalDate timestampToLocalDate(long timestamp) {
        return Instant.ofEpochMilli(timestamp).atZone(ZoneOffset.ofHours(8)).toLocalDate();
    }

    /**
     * 获取指定日期所在月份的开始或结束日期
     *
     * @param today
     * @param isFirst true 开始 false 结束
     * @return
     */
    public static LocalDate getStartOrEndDayOfMonth(LocalDate today, Boolean isFirst) {
        LocalDate resDate = LocalDate.now();
        if (today == null) {
            today = resDate;
        }
        Month month = today.getMonth();
        int length = month.length(today.isLeapYear());
        if (isFirst) {
            resDate = LocalDate.of(today.getYear(), month, 1);
        } else {
            resDate = LocalDate.of(today.getYear(), month, length);
        }
        return resDate;
    }

}
